home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / qix.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  12KB  |  419 lines

  1. /***************************************************************************
  2.  
  3.   machine\qix.c
  4.  
  5.   Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
  6.   I/O ports)
  7.  
  8. ***************************************************************************/
  9.  
  10. #include "driver.h"
  11. #include "timer.h"
  12. #include "cpu/m6809/m6809.h"
  13. #include "cpu/m6805/m6805.h"
  14. #include "6821pia.h"
  15.  
  16. static READ_HANDLER( sdungeon_coin_r );
  17. static WRITE_HANDLER( sdungeon_coinctrl_w );
  18. static WRITE_HANDLER( sdungeon_coin_w );
  19.  
  20. static READ_HANDLER( qix_sound_r );
  21. static WRITE_HANDLER( qix_dac_w );
  22. static void qix_pia_sint (int state);
  23. static void qix_pia_dint (int state);
  24. static int suspended;
  25.  
  26. static int sdungeon_coinctrl;
  27.  
  28.  
  29. /***************************************************************************
  30.  
  31.     Qix has 6 PIAs on board:
  32.  
  33.     From the ROM I/O schematic:
  34.  
  35.     PIA 1 = U11:
  36.         port A = external input (input_port_0)
  37.         port B = external input (input_port_1) (coin)
  38.     PIA 2 = U20:
  39.         port A = external input (???)
  40.         port B = external input (???)
  41.     PIA 3 = U30:
  42.         port A = external input (???)
  43.         port B = external input (???)
  44.  
  45.  
  46.     From the data/sound processor schematic:
  47.  
  48.     PIA 4 = U20:
  49.         port A = data CPU to sound CPU communication
  50.         port B = some kind of sound control
  51.         CA1 = interrupt signal from sound CPU
  52.         CA2 = interrupt signal to sound CPU
  53.     PIA 5 = U8:
  54.         port A = sound CPU to data CPU communication
  55.         port B = DAC value (port B)
  56.         CA1 = interrupt signal from data CPU
  57.         CA2 = interrupt signal to data CPU
  58.     PIA 6 = U7: (never actually used)
  59.         port A = unused
  60.         port B = sound CPU to TMS5220 communication
  61.         CA1 = interrupt signal from TMS5220
  62.         CA2 = write signal to TMS5220
  63.         CB1 = ready signal from TMS5220
  64.         CB2 = read signal to TMS5220
  65.  
  66. ***************************************************************************/
  67.  
  68. static struct pia6821_interface qix_pia_0_intf =
  69. {
  70.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
  71.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  72.     /*irqs   : A/B             */ 0, 0
  73. };
  74.  
  75. static struct pia6821_interface qixmcu_pia_0_intf =
  76. {
  77.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, sdungeon_coin_r, 0, 0, 0, 0,
  78.     /*outputs: A/B,CA/B2       */ 0, sdungeon_coin_w, 0, 0,
  79.     /*irqs   : A/B             */ 0, 0
  80. };
  81.  
  82. static struct pia6821_interface qix_pia_1_intf =
  83. {
  84.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, input_port_3_r, 0, 0, 0, 0,
  85.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  86.     /*irqs   : A/B             */ 0, 0
  87. };
  88.  
  89. static struct pia6821_interface qix_pia_2_intf =
  90. {
  91.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_4_r, 0, 0, 0, 0, 0,
  92.     /*outputs: A/B,CA/B2       */ 0, 0, 0, 0,
  93.     /*irqs   : A/B             */ 0, 0
  94. };
  95.  
  96. static struct pia6821_interface qixmcu_pia_2_intf =
  97. {
  98.     /*inputs : A/B,CA/B1,CA/B2 */ input_port_4_r, 0, 0, 0, 0, 0,
  99.     /*outputs: A/B,CA/B2       */ 0, sdungeon_coinctrl_w, 0, 0,
  100.     /*irqs   : A/B             */ 0, 0
  101. };
  102.  
  103. static struct pia6821_interface qix_pia_3_intf =
  104. {
  105.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  106.     /*outputs: A/B,CA/B2       */ pia_4_porta_w, 0, pia_4_ca1_w, 0,
  107.     /*irqs   : A/B             */ /*qix_pia_dint*/0, /*qix_pia_dint*/0
  108. };
  109.  
  110. static struct pia6821_interface qix_pia_4_intf =
  111. {
  112.     /*inputs : A/B,CA/B1,CA/B2 */ qix_sound_r, 0, 0, 0, 0, 0,
  113.     /*outputs: A/B,CA/B2       */ pia_3_porta_w, qix_dac_w, pia_3_ca1_w, 0,
  114.     /*irqs   : A/B             */ qix_pia_sint, qix_pia_sint
  115. };
  116.  
  117. static struct pia6821_interface qix_pia_5_intf =
  118. {
  119.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  120.     /*outputs: A/B,CA/B2       */ pia_3_porta_w, qix_dac_w, pia_3_ca1_w, 0,
  121.     /*irqs   : A/B             */ qix_pia_sint, qix_pia_sint
  122. };
  123.  
  124.  
  125. #if 0
  126. static pia6821_interface pia_intf_withmcu =
  127. {
  128.     6,                                                 /* 6 chips */
  129.     { PIA_DDRA, PIA_CTLA, PIA_DDRB, PIA_CTLB,
  130.       PIA_DDRA, PIA_CTLA, PIA_DDRB, PIA_CTLB },        /* offsets */
  131.     { input_port_0_r, input_port_2_r, input_port_4_r, 0, qix_sound_r, 0 },       /* input port A  */
  132.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CA1 */
  133.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CA2 */
  134.     { sdungeon_coin_r, input_port_3_r, 0, 0, 0, 0 }, /* input port B  */
  135.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CB1 */
  136.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CB2 */
  137.     { 0, 0, 0, pia_4_porta_w, pia_3_porta_w, 0 },   /* output port A */
  138.     { sdungeon_coin_w, 0, sdungeon_coinctrl_w, 0, qix_dac_w, 0 },  /* output port B */
  139.     { 0, 0, 0, pia_4_ca1_w, pia_3_ca1_w, 0 },       /* output CA2 */
  140.     { 0, 0, 0, 0, 0, 0 },                              /* output CB2 */
  141.     { 0, 0, 0, 0/*qix_pia_dint*/, qix_pia_sint, 0 },/* IRQ A */
  142.     { 0, 0, 0, 0/*qix_pia_dint*/, qix_pia_sint, 0 },/* IRQ B */
  143. };
  144.  
  145. static pia6821_interface pia_intf =
  146. {
  147.     6,                                                 /* 6 chips */
  148.     { PIA_DDRA, PIA_CTLA, PIA_DDRB, PIA_CTLB,
  149.       PIA_DDRA, PIA_CTLA, PIA_DDRB, PIA_CTLB },        /* offsets */
  150.     { input_port_0_r, input_port_2_r, input_port_4_r, 0, qix_sound_r, 0 },       /* input port A  */
  151.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CA1 */
  152.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CA2 */
  153.     { input_port_1_r, input_port_3_r, 0, 0, 0, 0 }, /* input port B  */
  154.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CB1 */
  155.     { 0, 0, 0, 0, 0, 0 },                           /* input bit CB2 */
  156.     { 0, 0, 0, pia_4_porta_w, pia_3_porta_w, 0 },   /* output port A */
  157.     { 0, 0, 0, 0, qix_dac_w, 0 },                   /* output port B */
  158.     { 0, 0, 0, pia_4_ca1_w, pia_3_ca1_w, 0 },       /* output CA2 */
  159.     { 0, 0, 0, 0, 0, 0 },                              /* output CB2 */
  160.     { 0, 0, 0, 0/*qix_pia_dint*/, qix_pia_sint, 0 },/* IRQ A */
  161.     { 0, 0, 0, 0/*qix_pia_dint*/, qix_pia_sint, 0 },/* IRQ B */
  162. };
  163. #endif
  164.  
  165.  
  166. unsigned char *qix_sharedram;
  167.  
  168.  
  169. READ_HANDLER( qix_sharedram_r )
  170. {
  171.     return qix_sharedram[offset];
  172. }
  173.  
  174.  
  175. WRITE_HANDLER( qix_sharedram_w )
  176. {
  177.     qix_sharedram[offset] = data;
  178. }
  179.  
  180.  
  181. WRITE_HANDLER( zoo_bankswitch_w )
  182. {
  183.     unsigned char *RAM = memory_region(REGION_CPU2);
  184.  
  185.  
  186.     if (data & 0x04) cpu_setbank (1, &RAM[0x10000])
  187.     else cpu_setbank (1, &RAM[0xa000]);
  188. }
  189.  
  190.  
  191. WRITE_HANDLER( qix_video_firq_w )
  192. {
  193.     /* generate firq for video cpu */
  194.     cpu_cause_interrupt(1,M6809_INT_FIRQ);
  195. }
  196.  
  197.  
  198.  
  199. WRITE_HANDLER( qix_data_firq_w )
  200. {
  201.     /* generate firq for data cpu */
  202.     cpu_cause_interrupt(0,M6809_INT_FIRQ);
  203. }
  204.  
  205.  
  206.  
  207. /* Return the current video scan line */
  208. READ_HANDLER( qix_scanline_r )
  209. {
  210.     /* The +80&0xff thing is a hack to avoid flicker in Electric Yo-Yo */
  211.     return (cpu_scalebyfcount(256) + 80) & 0xff;
  212. }
  213.  
  214. void withmcu_init_machine(void)
  215. {
  216.     suspended = 0;
  217.  
  218.     pia_unconfig();
  219.     pia_config(0, PIA_STANDARD_ORDERING | PIA_8BIT, &qixmcu_pia_0_intf);
  220.     pia_config(1, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_1_intf);
  221.     pia_config(2, PIA_STANDARD_ORDERING | PIA_8BIT, &qixmcu_pia_2_intf);
  222.     pia_config(3, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_3_intf);
  223.     pia_config(4, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_4_intf);
  224.     pia_config(5, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_5_intf);
  225.     pia_reset();
  226.  
  227.     sdungeon_coinctrl = 0x00;
  228. }
  229.  
  230. void qix_init_machine(void)
  231. {
  232.     suspended = 0;
  233.  
  234.     pia_unconfig();
  235.     pia_config(0, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_0_intf);
  236.     pia_config(1, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_1_intf);
  237.     pia_config(2, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_2_intf);
  238.     pia_config(3, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_3_intf);
  239.     pia_config(4, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_4_intf);
  240.     pia_config(5, PIA_STANDARD_ORDERING | PIA_8BIT, &qix_pia_5_intf);
  241.     pia_reset();
  242.  
  243.     sdungeon_coinctrl = 0x00;
  244. }
  245.  
  246. void zoo_init_machine(void)
  247. {
  248.     withmcu_init_machine();
  249. }
  250.  
  251.  
  252. /***************************************************************************
  253.  
  254.     6821 PIA handlers
  255.  
  256. ***************************************************************************/
  257.  
  258. static WRITE_HANDLER( qix_dac_w )
  259. {
  260.     DAC_data_w (0, data);
  261. }
  262.  
  263. READ_HANDLER( qix_sound_r )
  264. {
  265.     /* if we've suspended the main CPU for this, trigger it and give up some of our timeslice */
  266.     if (suspended)
  267.     {
  268.         timer_trigger (500);
  269.         cpu_yielduntil_time (TIME_IN_USEC (100));
  270.         suspended = 0;
  271.     }
  272.     return pia_4_porta_r (offset);
  273. }
  274.  
  275. static void qix_pia_dint (int state)
  276. {
  277.     /* not used by Qix, but others might use it; depends on a jumper on the PCB */
  278. }
  279.  
  280. static void qix_pia_sint (int state)
  281. {
  282.     /* generate a sound interrupt */
  283. /*    cpu_set_irq_line (2, M6809_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);*/
  284.  
  285.     if (state)
  286.     {
  287.         /* ideally we should use the cpu_set_irq_line call above, but it breaks */
  288.         /* sound in Qix */
  289.         cpu_cause_interrupt (2, M6809_INT_IRQ);
  290.  
  291.         /* wait for the sound CPU to read the command */
  292.         cpu_yielduntil_trigger (500);
  293.         suspended = 1;
  294.  
  295.         /* but add a watchdog so that we're not hosed if interrupts are disabled */
  296.         cpu_triggertime (TIME_IN_USEC (100), 500);
  297.     }
  298. }
  299.  
  300. /***************************************************************************
  301.  
  302.         68705 Communication
  303.  
  304. ***************************************************************************/
  305.  
  306. static unsigned char portA_in,portA_out,ddrA;
  307. static unsigned char portB_in,portB_out,ddrB;
  308. static unsigned char portC_in,portC_out,ddrC;
  309.  
  310. READ_HANDLER( sdungeon_68705_portA_r )
  311. {
  312. //logerror("PC: %x MCU PORTA R = %x\n",cpu_get_pc(),portA_in);
  313.     return (portA_out & ddrA) | (portA_in & ~ddrA);
  314. }
  315.  
  316. WRITE_HANDLER( sdungeon_68705_portA_w )
  317. {
  318. //logerror("PC: %x SD COINTOMAIN W: %x\n",cpu_get_pc(),data);
  319.     portA_out = data;
  320. }
  321.  
  322. WRITE_HANDLER( sdungeon_68705_ddrA_w )
  323. {
  324.     ddrA = data;
  325. }
  326.  
  327.  
  328. READ_HANDLER( sdungeon_68705_portB_r )
  329. {
  330.     portB_in = input_port_1_r(0) & 0x0F;
  331.     portB_in = portB_in | ((input_port_1_r(0) & 0x80) >> 3);
  332. //logerror("PC: %x MCU PORTB R = %x\n",cpu_get_pc(),portB_in);
  333.  
  334.     return (portB_out & ddrB) | (portB_in & ~ddrB);
  335. }
  336.  
  337. WRITE_HANDLER( sdungeon_68705_portB_w )
  338. {
  339. //logerror("PC: %x port B write %x\n",cpu_get_pc(),data);
  340.     portB_out = data;
  341. }
  342.  
  343. WRITE_HANDLER( sdungeon_68705_ddrB_w )
  344. {
  345.     ddrB = data;
  346. }
  347.  
  348.  
  349. READ_HANDLER( sdungeon_68705_portC_r )
  350. {
  351.     portC_in = (~sdungeon_coinctrl & 0x08) | ((input_port_1_r(0) & 0x70) >> 4);
  352. //logerror("PC: %x MCU PORTC R = %x\n",cpu_get_pc(),portC_in);
  353.  
  354.     return (portC_out & ddrC) | (portC_in & ~ddrC);
  355. }
  356.  
  357. WRITE_HANDLER( sdungeon_68705_portC_w )
  358. {
  359. //logerror("PC: %x port C write %x\n",cpu_get_pc(),data);
  360.     portC_out = data;
  361. }
  362.  
  363. WRITE_HANDLER( sdungeon_68705_ddrC_w )
  364. {
  365.     ddrC = data;
  366. }
  367.  
  368.  
  369.  
  370. READ_HANDLER( sdungeon_coin_r )
  371. {
  372.     return portA_out;
  373. }
  374.  
  375. static WRITE_HANDLER( sdungeon_coin_w )
  376. {
  377. //logerror("PC: %x COIN COMMAND W: %x\n",cpu_get_pc(),data);
  378.     /* this is a callback called by pia_0_w(), so I don't need to synchronize */
  379.     /* the CPUs - they have already been synchronized by sdungeon_pia_0_w() */
  380.     portA_in = data;
  381. }
  382.  
  383. static WRITE_HANDLER( sdungeon_coinctrl_w )
  384. {
  385. //logerror("PC: %x COIN CTRL W: %x\n",cpu_get_pc(),data);
  386.     if (data & 0x04)
  387.     {
  388.         cpu_set_irq_line(3,M6809_IRQ_LINE,ASSERT_LINE);
  389.         /* spin for a while to let the 68705 write the result */
  390.         cpu_spinuntil_time(TIME_IN_USEC(50));
  391.     }
  392.     else
  393.         cpu_set_irq_line(3,M6809_IRQ_LINE,CLEAR_LINE);
  394.  
  395.     /* this is a callback called by pia_0_w(), so I don't need to synchronize */
  396.     /* the CPUs - they have already been synchronized by sdungeon_pia_0_w() */
  397.     sdungeon_coinctrl = data;
  398. }
  399.  
  400.  
  401. static void pia_0_w_callback(int param)
  402. {
  403.     pia_0_w(param >> 8,param & 0xff);
  404. }
  405.  
  406. WRITE_HANDLER( sdungeon_pia_0_w )
  407. {
  408. //logerror("%04x: PIA 1 write offset %02x data %02x\n",cpu_get_pc(),offset,data);
  409.  
  410.     /* Hack: Kram and Zoo Keeper for some reason (protection?) leave the port A */
  411.     /* DDR set to 0xff, so they cannot read the player 1 controls. Here I force */
  412.     /* the DDR to 0, so the controls work correctly. */
  413.     if (offset == 0) data = 0;
  414.  
  415.     /* make all the CPUs synchronize, and only AFTER that write the command to the PIA */
  416.     /* otherwise the 68705 will miss commands */
  417.     timer_set(TIME_NOW,data | (offset << 8),pia_0_w_callback);
  418. }
  419.